package socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 服务端
 *
 * 使用豆包AI丰富Server功能，实现广播消息的操作
 * 豆包提示词:
 * 基于上述代码，实现服务端可以广播消息的操作，将任意一个客户端发送过来的消息转发给所有客户端。
 *
 *
 */
public class Server {
    private ServerSocket serverSocket;
    // 维护所有连接的客户端Socket，使用线程安全的集合
    private Set<Socket> clientSockets = Collections.synchronizedSet(new HashSet<>());
    //线程池
    private ExecutorService pool;

    public Server(){
        try {
            System.out.println("正在启动服务端...");
            serverSocket = new ServerSocket(8088);
            pool = Executors.newFixedThreadPool(20);
            System.out.println("服务端启动成功！");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){
        try {
            while(true) {
                System.out.println("等待客户端链接...");
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端链接了!");

                // 将新连接的客户端添加到集合中
                clientSockets.add(socket);

                // 启动一个线程来处理该客户端交互
                ClientHandler handler = new ClientHandler(socket);
//                Thread t = new Thread(handler);
//                t.start();
                pool.execute( handler);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 广播消息给所有客户端
     * @param message 要广播的消息
     */
    private void broadcast(String message) {
        // 将消息转换为字节数组
        byte[] data = message.getBytes(StandardCharsets.UTF_8);

        // 遍历所有客户端Socket，发送消息
        for (Socket socket : clientSockets) {
            try {
                OutputStream out = socket.getOutputStream();
                // 先发送消息长度，再发送消息内容
                out.write(data.length);
                out.write(data);
                out.flush();
            } catch (IOException e) {
                System.out.println("发送消息给客户端时发生错误: " + e.getMessage());
            }
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }

    /**
     * 该线程负责与指定的客户端交互
     */
    private class ClientHandler implements Runnable{
        private Socket socket;

        public ClientHandler(Socket socket){
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                InputStream in = socket.getInputStream();
                int len;

                // 读取客户端发送的消息
                while((len = in.read()) != -1) {
                    byte[] data = new byte[len];
                    in.read(data);
                    String message = new String(data, StandardCharsets.UTF_8);
                    System.out.println("客户端说:" + message);

                    // 广播消息给所有客户端
                    broadcast(message);
                }
            } catch (IOException e) {
                System.out.println("与客户端的连接断开: " + e.getMessage());
            } finally {
                // 客户端断开连接时，从集合中移除
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                clientSockets.remove(socket);
                System.out.println("一个客户端已断开连接，当前在线人数: " + clientSockets.size());
            }
        }
    }
}
